<?php
namespace app\index\controller;

use app\index\model\User;
use app\index\model\WeatherCity;
use app\index\model\SubwayCity;
use think\App;
use think\Controller;
use think\Request;
use think\facade\Request as Req;
use Config;

class WeChat extends Controller
{
    public function __construct(App $app = null , Request $request)
    {
        parent::__construct($app);
        $this->request = $request;
    }

    /**
     * 微信首页
     */
    public function index()
    {
        $request = $this->request->param(false);
        if(!empty($request)){
            if(Req::has('code')){//处理网页授权
                $app_config = Config::get('Wechat.');
                $web_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$app_config['app_id']."&secret=".$app_config['app_secret']."&code=".$request['code']."&grant_type=authorization_code";
                $res = json_decode($this->httpGet($web_token_url),true);
                //刷新token链接
                // $web_refresh_token = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
                  //获取用户信息
                $web_token = isset($res['access_token']) ? $res['access_token'] : '';
                $openid = isset($res['openid']) ? $res['openid'] : '';
                $user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$web_token."&openid=".$openid."&lang=zh_CN";
                $user_info = json_decode($this->httpGet($user_info_url),true);
                $id = isset($user_info['openid']) ? $user_info['openid'] : "";
                $account = isset($user_info['nickname']) ? $user_info['nickname'] : "";
                $sex = isset($user_info['sex']) ? $user_info['sex'] : "";
                $country = isset($user_info['country']) ? $user_info['country'] : "";
                $province = isset($user_info['province']) ? $user_info['province'] : "";
                $city = isset($user_info['city']) ? $user_info['city'] : "";
                $is_user = User::where(array('wx_open_id' => $id))->find();
                if(empty($is_user)){
                    $user = new User();
                    $save_ret = $user->save(
                        [
                            'account' => $account,
                            'wx_open_id' => $id,
                            'sex' => $sex,
                            'address' => $country.$province.$city
                        ]
                    );
                    if(!$save_ret){
                        return '系统故障，请稍后重试';
                    }
                }
          }else{
              $this->handleMessage();
          }
        }else{
          return $request;
        }
      return $this->fetch();
    }
    /**
     * 微信服务范围
     */
    public function service()
    {
//        $request = $this->request->param(false);
//        if(!empty($request)){
//            if(Req::has('code')){//处理网页授权
//                $app_config = Config::get('Wechat.');
//                $web_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$app_config['app_id']."&secret=".$app_config['app_secret']."&code=".$request['code']."&grant_type=authorization_code";
//                $res = json_decode($this->httpGet($web_token_url),true);
//                //刷新token链接
//                // $web_refresh_token = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
//                //获取用户信息
//                $web_token = isset($res['access_token']) ? $res['access_token'] : '';
//                $openid = isset($res['openid']) ? $res['openid'] : '';
//                $user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$web_token."&openid=".$openid."&lang=zh_CN";
//                $user_info = json_decode($this->httpGet($user_info_url),true);
//                $id = isset($user_info['openid']) ? $user_info['openid'] : "";
//                $account = isset($user_info['nickname']) ? $user_info['nickname'] : "";
//                $sex = isset($user_info['sex']) ? $user_info['sex'] : "";
//                $country = isset($user_info['country']) ? $user_info['country'] : "";
//                $province = isset($user_info['province']) ? $user_info['province'] : "";
//                $city = isset($user_info['city']) ? $user_info['city'] : "";
//                $is_user = User::where(array('wx_open_id' => $id))->find();
//                if(empty($is_user)){
//                    $user = new User();
//                    $save_ret = $user->save(
//                        [
//                            'account' => $account,
//                            'wx_open_id' => $id,
//                            'sex' => $sex,
//                            'address' => $country.$province.$city
//                        ]
//                    );
//                    if(!$save_ret){
//                        return '系统故障，请稍后重试';
//                    }
//                }
//            }else{
//                $this->handleMessage();
//            }
//        }else{
//            return $request;
//        }
        return $this->fetch();
    }
    /**
     * 微信产品及支付
     */
    public function product()
    {
//        $request = $this->request->param(false);
//        if(!empty($request)){
//            if(Req::has('code')){//处理网页授权
//                $app_config = Config::get('Wechat.');
//                $web_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$app_config['app_id']."&secret=".$app_config['app_secret']."&code=".$request['code']."&grant_type=authorization_code";
//                $res = json_decode($this->httpGet($web_token_url),true);
//                //刷新token链接
//                // $web_refresh_token = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
//                //获取用户信息
//                $web_token = isset($res['access_token']) ? $res['access_token'] : '';
//                $openid = isset($res['openid']) ? $res['openid'] : '';
//                $user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$web_token."&openid=".$openid."&lang=zh_CN";
//                $user_info = json_decode($this->httpGet($user_info_url),true);
//                $id = isset($user_info['openid']) ? $user_info['openid'] : "";
//                $account = isset($user_info['nickname']) ? $user_info['nickname'] : "";
//                $sex = isset($user_info['sex']) ? $user_info['sex'] : "";
//                $country = isset($user_info['country']) ? $user_info['country'] : "";
//                $province = isset($user_info['province']) ? $user_info['province'] : "";
//                $city = isset($user_info['city']) ? $user_info['city'] : "";
//                $is_user = User::where(array('wx_open_id' => $id))->find();
//                if(empty($is_user)){
//                    $user = new User();
//                    $save_ret = $user->save(
//                        [
//                            'account' => $account,
//                            'wx_open_id' => $id,
//                            'sex' => $sex,
//                            'address' => $country.$province.$city
//                        ]
//                    );
//                    if(!$save_ret){
//                        return '系统故障，请稍后重试';
//                    }
//                }
//            }else{
//                $this->handleMessage();
//            }
//        }else{
//            return $request;
//        }
        return $this->fetch();
    }
    /**
     * 校验微信服务器
     */
    public function checkSignature()
    {
        if($this->request->get('echostr')){
            $signature = $this->request->param('signature');
            $timestamp = $this->request->param('timestamp');
            $nonce = $this->request->param('nonce');
            $token = '9s5T1R2uf2o0r20';
            $tmpArr = array($token,$timestamp,$nonce);
            sort($tmpArr);
            $tmpStr = implode($tmpArr);
            $tmpStr = sha1($tmpStr);

            if ($tmpStr == $signature) {
                //避坑：此处如果按照微信官方文档返回true则会报错
                echo $this->request->param('echostr');die;
            }
        }else{
            //使用ThinkPHP5内置接受post数据方法无法接收到xml
            $postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
            if (!empty($postStr)){
                $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
                $RX_TYPE = trim($postObj->MsgType);

                $EVENT = $postObj->Event;
                //用户发送的消息类型判断
                switch ($RX_TYPE)
                {
                    case "event":
                        if($EVENT == "subscribe"){
                            $result = $this->receiveText($postObj,'first');
                        }
                        break;
                    case "text":    //文本消息
                        $result = $this->receiveText($postObj);
                        break;
                    case "image":   //图片消息
                        $result = $this->receiveImage($postObj);
                        break;

                    case "voice":   //语音消息
                        $result = $this->receiveVoice($postObj);
                        break;
                    case "video":   //视频消息
                        $result = $this->receiveVideo($postObj);
                        break;
                    case "location"://位置消息
                        $result = $this->receiveLocation($postObj);
                        break;
                    case "link":    //链接消息
                        $result = $this->receiveLink($postObj);
                        break;
                    default:
                        $result = "unknow msg type: ".$RX_TYPE;
                        break;
                }
                echo $result;
            }else {
                echo "";
                exit;
            }
        }
    }
    /**
     * 发送文本消息
     */
    private function receiveText($object,$type = '')
    {
        $map_key = Config::get('Wechat.map_key');
        if(!empty($type)){
            $content = "你好，欢迎来到暖安软件！\r\n";
            $content .= "主要提供网站建设维护服务\r\n";
            $content .= "同时提供文字+语音查询功能\r\n";
            $content .= "支持查天气：【查天气北京】\r\n";
            $content .= "IP定位：【查IP123.234.11.5】\r\n";
            $content .= "支持在线翻译：【请翻译apple】\r\n";
            $content .= "支持查地铁线路：【查地铁北京】\r\n";
            $content .= "语音查询按如上格式说即可！";
        }else{
            if(strpos($object->Content,'天气') !== false){
                //查询天气
                $city = mb_substr($object->Content,3,strlen($object->Content)-3,'utf8');
                $city_info = WeatherCity::where('city_name','like','%'.$city.'%')->find();
                if(empty($city_info)){
                    $content = '获取城市信息失败，请输入国内正确城市';
                }else{
                    $url = "https://restapi.amap.com/v3/weather/weatherInfo?key=".$map_key."&city=".$city_info['city_id']."&extensions=all&output=JSON";

                    // $content = $this->httpGet($url);
                    $result = json_decode($this->httpGet($url),true);
                    if($result['status'] != 1){//获取失败
                        $content = '获取天气信息失败，请稍后重试';
                    }else{
                        $content = $result['forecasts'][0]['city']."天气情况如下：\r\n";
                        $content .= "今天：".$result['forecasts'][0]['casts'][0]['dayweather']."\r\n";
                        $content .= "温度：".$result['forecasts'][0]['casts'][0]['nighttemp']."-".$result['forecasts'][0]['casts'][0]['daytemp']."\r\n";
                        $content .= "风向：".$result['forecasts'][0]['casts'][0]['daywind']."\r\n";
                        $content .= "风力：".$result['forecasts'][0]['casts'][0]['daypower']."\r\n";
                        $content .= "明天：".$result['forecasts'][0]['casts'][1]['dayweather'].",温度：".$result['forecasts'][0]['casts'][1]['nighttemp']."-".$result['forecasts'][0]['casts'][1]['daytemp'];
                    }
                }
            }else if(strpos($object->Content,'ip') !== false || strpos($object->Content,'IP') !== false){

                $ip = mb_substr($object->Content,3,strlen($object->Content)-3,'utf8');
                $url = "https://restapi.amap.com/v3/ip?key=".$map_key."&ip=".$ip."&output=JSON";
                $result = json_decode($this->httpGet($url),true);
                if($result['status'] != 1){
                    $content = '获取IP定位失败，请稍后重试';
                }else{
                    $content = $ip."定位结果为：".$result['province'].$result['city'];
                }
            }else if(strpos($object->Content,'地铁') !== false){
                $city = mb_substr($object->Content,3,strlen($object->Content)-3,'utf8');
                $city_info = SubwayCity::where('city_name','like','%'.$city.'%')->find();
                $content = $city_info['city_name']."地铁线路图URL：".$city_info['subway_pic'];
            }else if(strpos($object->Content,'翻译') !== false){
            	$word = mb_substr($object->Content,3,strlen($object->Content)-3,'utf8');
            	$salt = "h1el2los3trup4hp";
		    	$sign = md5("20190404000284619".$word.$salt."_q8MAQATZKymZExwlf4L");
		        $url = "http://api.fanyi.baidu.com/api/trans/vip/translate?q=".$word."&from=auto&to=auto&appid=20190404000284619&salt=".$salt."&sign=".$sign;
		        $result = json_decode($this->httpGet($url),true);
		        if(isset($result['error_code'])){//有错误
		        	$content = "翻译失败，请重试";
		        }else{
		        	$content = $result['trans_result'][0]['dst'];
		        }
            }else if(strpos($object->Content,'身份证') !== false){

            }else if(strpos($object->Content,'讲个笑话') !== false){

            }else{
            	$content = $object->Content;
            }
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /*
     * 接收图片消息
     */
    private function receiveImage($object)
    {
        $content = "你发送的是图片，地址为：".$object->PicUrl;
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /*
     * 接收语音消息
     */
    private function receiveVoice($object)
    {
        $map_key = Config::get('Wechat.map_key');
        if(strpos($object->Recognition,'天气') !== false){
            // 查询天气
            $city_one = mb_substr($object->Recognition,3,strlen($object->Recognition)-3,'utf8');
            $city = mb_substr($city_one,0,-1,'utf8');
            $city_info = WeatherCity::where('city_name','like','%'.$city.'%')->find();
            if(empty($city_info)){
                $content = '获取城市信息失败，请输入国内正确城市';
            }else{
                $url = "https://restapi.amap.com/v3/weather/weatherInfo?key=".$map_key."&city=".$city_info['city_id']."&extensions=all&output=JSON";

                // $content = $this->httpGet($url);
                $result = json_decode($this->httpGet($url),true);
                if($result['status'] != 1){//获取失败
                    $content = '获取天气信息失败，请稍后重试';
                }else{
                    $content = $result['forecasts'][0]['city']."天气情况如下：\r\n";
                    $content .= "今天：".$result['forecasts'][0]['casts'][0]['dayweather']."\r\n";
                    $content .= "温度：".$result['forecasts'][0]['casts'][0]['nighttemp']."-".$result['forecasts'][0]['casts'][0]['daytemp']."\r\n";
                    $content .= "风向：".$result['forecasts'][0]['casts'][0]['daywind']."\r\n";
                    $content .= "风力：".$result['forecasts'][0]['casts'][0]['daypower']."\r\n";
                    $content .= "明天：".$result['forecasts'][0]['casts'][1]['dayweather'].",温度：".$result['forecasts'][0]['casts'][1]['nighttemp']."-".$result['forecasts'][0]['casts'][1]['daytemp'];
                }
            }
        }else if(strpos($object->Recognition,'ip') !== false || strpos($object->Recognition,'IP') !== false){
            $ip_one = mb_substr($object->Recognition,3,strlen($object->Recognition)-3,'utf8');
            $ip = mb_substr($ip_one,0,-1,'utf8');
            $url = "https://restapi.amap.com/v3/ip?key=".$map_key."&ip=".$ip."&output=JSON";
            $result = json_decode($this->httpGet($url),true);
            if($result['status'] != 1){
                $content = '获取IP定位失败，请稍后重试';
            }else{
                $content = $ip."定位结果为：".$result['province'].$result['city'];
            }
        }else if(strpos($object->Recognition,'地铁') !== false){
        	$city_one = mb_substr($object->Recognition,3,strlen($object->Recognition)-3,'utf8');
        	$city = mb_substr($city_one,0,-1,'utf8');
            $city_info = SubwayCity::where('city_name','like','%'.$city.'%')->find();
            $content = $city_info['city_name']."地铁线路图URL：".$city_info['subway_pic'];
        }else if(strpos($object->Recognition,'翻译') !== false){
        	$word_one = mb_substr($object->Recognition,3,strlen($object->Recognition)-3,'utf8');
        	$word = mb_substr($word_one,0,-1,'utf8');
        	$salt = "h1el2los3trup4hp";
	    	$sign = md5("20190404000284619".$word.$salt."_q8MAQATZKymZExwlf4L");
	        $url = "http://api.fanyi.baidu.com/api/trans/vip/translate?q=".$word."&from=auto&to=auto&appid=20190404000284619&salt=".$salt."&sign=".$sign;
	        $result = json_decode($this->httpGet($url),true);
	        if(isset($result['error_code'])){//有错误
	        	$content = "翻译失败，请重试";
	        }else{
	        	$content = $result['trans_result'][0]['dst'];
	        }
        }else{
            $content = $object->Recognition;
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /*
     * 接收视频消息
     */
    private function receiveVideo($object)
    {
        $content = "你发送的是视频，媒体ID为：".$object->MediaId;
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /*
     * 接收位置消息
     */
    private function receiveLocation($object)
    {
        $content = "你发送的是位置，纬度为：".$object->Location_X."；经度为：".$object->Location_Y."；缩放级别为：".$object->Scale."；位置为：".$object->Label;
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /*
     * 接收链接消息
     */
    private function receiveLink($object)
    {
        $content = "你发送的是链接，标题为：".$object->Title."；内容为：".$object->Description."；链接地址为：".$object->Url;
        $result = $this->transmitText($object, $content);
        return $result;
    }
    /**
     * 文本消息内容
     */
    private function transmitText($object, $content)
    {
        $textTpl = "<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[text]]></MsgType>
                    <Content><![CDATA[%s]]></Content>
                    </xml>";
        $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $result;
    }
    /**
     * 对外获取token
     */
    public function tokenApi()
    {
        $token = $this->getAccessToken();
        var_dump($token);
    }

    /**
     * 获取access_token
     */
    private function getAccessToken()
    {
        $app_config = Config::get('wechat.');
        if(!file_exists('../token.php')){
            $f = fopen('../token.php','w');
            fclose($f);
        }
        $token = json_decode($this->get_php_file('../token.php'),true);

        if(!isset($token['expire_time']) || $token['expire_time'] < time()){//token超时，需要重新获取
            $wx_config = Config::get('wechat.');
            $url = $wx_config['access_token_url'].'appid='.$wx_config['app_id'].'&secret='.$wx_config['app_secret'];
            $res = json_decode($this->httpGet($url));
            $access_token = $res->access_token;
            if ($access_token) {
                $new_token['expire_time'] = time() + 7000;
                $new_token['access_token'] = $access_token;
                $this->set_php_file("../token.php", json_encode($new_token));
            }
            return $access_token;
        }else{
            return $token['access_token'];
        }

    }
    /**
     * 对外获取material
     */
    public function materialApi()
    {
        $token = $this->getMaterial();
        var_dump($token);
    }
    /**
     * 获取素材
     */
    private function getMaterial(){
        $access_token = $this->getAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=".$access_token;
        $data = [
            'type' => 'image',
            'offset' => 15,
            'count' => 20,
        ];
        $data = json_encode($data,JSON_UNESCAPED_UNICODE);
        $material = json_decode($this->httpPost($url,$data));
        return $material;
    }
    /**
     * 获取文件的access_token
     */
    private function get_php_file($path)
    {
        return trim(substr(file_get_contents($path), 15));
    }

    /**
     * 将获取到的access_token存储到文件中
     */
    private function set_php_file($filename, $content)
    {
        $fp = fopen($filename, "w");
        fwrite($fp, "<?php exit();?>" . $content);
        fclose($fp);
    }

    /**
     * curl_get请求
     */
    private function httpGet($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        // 为保证第三方服务器与微信服务器之间数据传输的安全性，所有微信接口采用https方式调用，必须使用下面2行代码打开ssl安全校验。
        // 如果在部署过程中代码在此处验证失败，请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($curl, CURLOPT_URL, $url);

        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }

    /**
     * curl_post请求
     */
    private function httpPost($url,$data)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url); //要访问的URL
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        //POST
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //文件流返回

        $res = curl_exec($curl);
        if(curl_errno($curl)){
            echo curl_error($curl);die;
        }
        curl_close($curl);
        return $res;
    }

    /**
     * 自定义菜单
     */
    public function createMenu()
    {
        $access_token = $this->getAccessToken();
        $create_url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token='.$access_token;
        $app_config = Config::get('wechat.');
        $call_back_url = urlencode('http://www.struphp.com/wechat');
        $menu = [
          'button' => [
              [
                  "type" => "view",
                  "name" => "首页",
                  "url" => "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$app_config['app_id']."&redirect_uri=".$call_back_url."&response_type=CODE&scope=snsapi_userinfo&state=STATE#wechat_redirect"
              ],
              [
                  "type" => "view",
                  "name" => "案例",
                  "url" => "http://www.struphp.com"
              ],
              [
                  "name" => "服务",
                  "sub_button" => [
                        [
                            "type" =>  "click",
                            "name" => "服务简介",
                            "key" => "stru_server_01",
                        ],
                      [
                          "type" =>  "click",
                          "name" => "产品展示",
                          "key" => "stru_server_02",
                      ],
                  ]
              ]
          ]
        ];

        $menu = json_encode($menu,JSON_UNESCAPED_UNICODE);
        $res = json_decode($this->httpPost($create_url,$menu),true);
        if($res['errcode'] == 0){
            echo '创建自定义菜单成功';
        }else if($res['errcode'] == 40018){
            echo "菜单名长度无效";
        }else{
            echo $res['errmsg'];
        }
    }
}
